package com.example.demo.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

@Component
public class JwtUtil {

    private final static Logger logger = LoggerFactory.getLogger(JwtUtil.class);

//    新增；ThreadLocal存储当前用户ID
    private static final ThreadLocal<String> currentUserId = new ThreadLocal<>();

//    存储、获取当前用户信息的上下文
    public static void setCurrentUserId(String userId) {
        currentUserId.set(userId);
    }
    public static String getCurrentUserId() {
        return currentUserId.get();
    }
//    清除当前用户的信息
    public static void clearCurrentUserId() {
        currentUserId.remove();
    }

    // 私钥
    @Value("${jwt.privateKey}")
    private String privateKey;

    // 公钥
    @Value("${jwt.publicKey}")
    private String publicKey;

    // 将转换为单行的私钥和公钥字符串还原为多行的PEM格式
    public String getPrivateKey() {
        return privateKey.replace("\\n", "\n");
    }

    public String getPublicKey() {
        return publicKey.replace("\\n", "\n");
    }

    //    加载私钥
    private PrivateKey loadPrivateKey(String privateKeyPem) {
        String privateKeyPEM = privateKeyPem
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s", ""); // 移除所有空白字符
        byte[] encoded = Base64.getDecoder().decode(privateKeyPEM);
        // 验证是否为空
        if (privateKeyPEM.isEmpty()) {
            throw new IllegalArgumentException("Private key is empty");
        }
        try {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(keySpec);
        } catch (Exception e) {
            logger.error("Failed to load private key", e);
            throw new RuntimeException("Failed to load private key", e);
        }
    }

    //    加载公钥
    private PublicKey loadPublicKey(String publicKeyPem) {
        String publicKeyPEM = publicKeyPem
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s", ""); // 移除所有空白字符
        byte[] encoded = Base64.getDecoder().decode(publicKeyPEM);
        // 验证是否为空
        if (publicKeyPEM.isEmpty()) {
            throw new IllegalArgumentException("Public key is empty");
        }
        try {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePublic(keySpec);
        } catch (Exception e) {
            logger.error("Failed to load public key", e);
            throw new RuntimeException("Failed to load public key", e);
        }
    }

    // 生成JWT
    public String generateToken(Map<String, Object> claims, String subject, long validityPeriodMillis) {
        if (validityPeriodMillis <= 0) {
            throw new IllegalArgumentException("Validity period must be greater than zero");
        }
        PrivateKey privateKey = loadPrivateKey(getPrivateKey());
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        Date validity = new Date(nowMillis + validityPeriodMillis); // 设置 Token 过期时间

        return Jwts.builder()
                .claims(claims)
                .subject(subject)
                .issuedAt(now)
                .expiration(validity)
                .signWith(privateKey, SignatureAlgorithm.RS256)
                .compact();
    }

    // 验证JWT
    public Claims verifyToken(String token) {
//        System.out.println("在Verify中获得的token是：" + token);
        if (!token.contains(".") || token.split("\\.").length != 3) {
            logger.warn("Verify Invalid JWT format: " + token);
        }
        try {
            PublicKey publicKey = loadPublicKey(getPublicKey());
            return Jwts.parser()
                    .verifyWith(publicKey)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (Exception e) {
            logger.error("Failed to verify token {}", e.getMessage());
            throw new RuntimeException("Failed to verify token", e);
        }
    }

    // 验证JWT令牌（token）
    public boolean validateToken(String token) {
        if (!token.contains(".") || token.split("\\.").length != 3) {
            logger.warn("Validate Invalid JWT format: " + token);
            return false;
        }
        try {
            PublicKey publicKey = loadPublicKey(getPublicKey());
            Jwts.parser()
                    .verifyWith(publicKey)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
            return true;
        } catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    //    get userId by token
    public String getUserIdFromToken(String token) {
        try {
//            解析token并获取Claims
            Claims claims = verifyToken(token);
            return claims.get("uuId", String.class);
        } catch (JwtException e) {
            logger.error("Failed to get user ID from token", e);
            return null;
        }
    }

//    get username by token
    public String getUsernameFromToken(String token) {
        try {
            Claims claims = verifyToken(token);
            return claims.getSubject();
        } catch (JwtException e) {
            logger.error("Failed to get username from token", e);
            return null;
        }
    }



}